package com.example.demo.encog;

import org.encog.Encog;
import org.encog.engine.network.activation.ActivationSigmoid;
import org.encog.ml.data.MLData;
import org.encog.ml.data.MLDataPair;
import org.encog.ml.data.MLDataSet;
import org.encog.ml.data.basic.BasicMLDataSet;
import org.encog.neural.networks.BasicNetwork;
import org.encog.neural.networks.layers.BasicLayer;
import org.encog.neural.networks.training.propagation.resilient.ResilientPropagation;
import org.encog.persist.EncogDirectoryPersistence;

import java.io.File;

/**
 * @Create: IntelliJ IDEA.
 * @Author: subtlman_ljx
 * @Date: 2022/10/14/10:55
 * @Description:
 */
public class T {

    /**
     * 1、从代码层面来看
     * 创建一个神经网络
     * 添加神经图层
     * 确定神经结构
     *
     * 引入训练数据
     *
     * 关联处理后的神经网络和训练数据
     *
     * 2、联想
     * 线程存储在树节点中
     * 借助对象关联在树节点中
     *
     * 参考网址 https://blog.csdn.net/u012970287/article/details/79872495
     * 材料网址
     * https://blog.51cto.com/u_15077537/4523720
     * https://www.cnblogs.com/codeDog123/p/6754391.html
     * http://t.zoukankan.com/quietwalk-p-7524427.html
     * https://www.cnblogs.com/subtlman/p/16791456.html
     * https://www.heatonresearch.com/encog/
     * @param args
     */

    public static void main(String[] args) {
       getInstance().t1();

    }


    String filename="D:\\IDEA\\workspace1\\demo2\\src\\main\\java\\com\\example\\demo\\encog\\encogback.eg";

    public static T getInstance(){
        return new T();
    }

    public void t1(){
        //使用训练模型，不用再次创建神经网络，不用再次训练数据
        System.out.println("loading network");
        BasicNetwork network = (BasicNetwork) EncogDirectoryPersistence.loadObject(new File(filename));
        //创建训练数据
        double XOR_INPUT[][] = {{0.0, 1.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}};
        double XOR_OUTPUT[][] = {{1.0}, {1.0}, {1.0}, {0.0}};
        MLDataSet trainingSet = new BasicMLDataSet(XOR_INPUT,XOR_OUTPUT);
        double e = network.calculateError(trainingSet);
        System.out.println("Network trained`s error is(should be same as above):"+e); // 6.991768111366914E-4

        System.out.println("Neural Network Results: ");
        for(MLDataPair pair: trainingSet){
            final MLData output = network.compute(pair.getInput());
            System.out.println(pair.getInput().getData(0) +
                    "," + pair.getInput().getData(1) +
                    ", actual=" + output.getData(0) + ",ideal=" +
                    pair.getIdeal().getData(0));
        }

    }

    public void t2(){
        //神经网络 创建、训练、保存eg文件
        //创建一个神经网络
        BasicNetwork network = new BasicNetwork();

        //BasicLayer 参数： 激活函数、是否偏移、该层神经元数目
        network.addLayer(new BasicLayer(null, true, 2));
        network.addLayer(new BasicLayer(new ActivationSigmoid(), true, 3));
        network.addLayer(new BasicLayer(new ActivationSigmoid(), true, 1));
        network.getStructure().finalizeStructure();

        // 使用Nguyen Widrow随机重置权重矩阵和偏差值，范围在-1和1之间的。
        // 如果网络没有输入、输出或隐藏层，则不能使用Nguyen Widrow，将使用-1到1之间的简单随机范围
        network.reset();

        //创建训练数据
        double XOR_INPUT[][] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}};
        double XOR_OUTPUT[][] = {{0.0}, {1.0}, {1.0}, {0.0}};
        MLDataSet trainingSet = new BasicMLDataSet(XOR_INPUT,XOR_OUTPUT);

        //训练神经网络
        final ResilientPropagation train = new ResilientPropagation(network, trainingSet);

        int epoch = 1;

        do {
            train.iteration();
            System.out.println("Epoch #" + epoch + " Error: " + train.getError());
            epoch++;
        }while(train.getError() > 0.001);

        //保存神经网络
        double e = network.calculateError(trainingSet);
        System.out.println("Network trained to error:"+e); // 0.001869494889330012 9.876912370293156E-4
        System.out.println("Saving network");
        EncogDirectoryPersistence.saveObject(new File(filename),network);


        //测试神经网络
        System.out.println("Neural Network Results: ");
        for(MLDataPair pair: trainingSet){
            final MLData output = network.compute(pair.getInput());
            System.out.println(pair.getInput().getData(0) +
                    "," + pair.getInput().getData(1) +
                    ", actual=" + output.getData(0) + ",ideal=" +
                    pair.getIdeal().getData(0));
        }
        //Encog关闭
        Encog.getInstance().shutdown();
    }


}
